package com.mrx.commons.redis.proxy;

import com.mrx.commons.redis.FakeValueOperations;
import io.lettuce.core.RedisException;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.context.ApplicationEventPublisher;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * @author Mr.X
 * @since 2023-04-28 11:19
 **/
public class ValueOperationsProxy<T extends FakeValueOperations<?, ?>> implements IProxyHelper<T> {

    private final T proxyObj;

    private final T target;

    @SuppressWarnings("unchecked")
    private ValueOperationsProxy(T value) {
        Enhancer enhancer = new Enhancer();
        enhancer.setCallback(this);
        enhancer.setSuperclass(value.getClass());
        Class<?>[] argumentTypes = {Map.class, ApplicationEventPublisher.class};
        Object[] arguments = {value.getFakeRedis(), value.getPublisher()};
        proxyObj = (T) enhancer.create(argumentTypes, arguments);
        this.target = value;
    }

    public static <T extends FakeValueOperations<?, ?>> T createProxy(T obj) {
        return new ValueOperationsProxy<>(obj).proxyObj;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        try {
            return methodProxy.invokeSuper(proxyObj, objects);
        } catch (RedisException e) {
            throw handleException(target, method);
        }
    }

}
